package com.ltg.framework.es.utils;

import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;

import java.io.Serializable;
import java.util.List;
import java.util.Objects;

/**
 * <p>boolQuery构造器就是在bool中按多值搜索 <p/>
 * ```json
 *{
 *     "from": 0,
 *     "size": 10
 *     "query": {
 *         "bool": {
 *             "must": [
 *                  {}
 *                  .....
 *             ]
 *         }
 *     },
 * }
 * ```
 * es BoolQueryBuilder构造器
 * @author LTG
 */
public class BoolQueryBuilderUtils {

    /**
     * 同一字段满足不同值
     *
     * @param boolQueryBuild
     * @param field
     * @param values
     */

    public static void addShould(BoolQuery.Builder boolQueryBuild, String field, List<String> values) {
        boolQueryBuild.must(mustQueryBuild -> mustQueryBuild.bool(boolQuery -> {
            for (String value : values) {
                boolQuery.should(show -> show.matchPhrase(a -> a.field(field).query(value)));
            }
            return boolQuery;
        }));
    }


    /**
     * 多字满足统一值
     *
     * @param boolQueryBuild
     * @param fields
     * @param value
     */
    public static void addShould(BoolQuery.Builder boolQueryBuild, List<String> fields, String value) {
        boolQueryBuild.must(mustQueryBuild -> mustQueryBuild.bool(boolQuery -> {
            for (String fieId : fields) {
                boolQuery.should(show -> show.matchPhrase(a -> a.field(fieId).query(value)));
            }
            return boolQuery;
        }));
    }


    /**
     * 单字段搜索
     *
     * @param boolQueryBuild
     * @param field
     * @param value
     */
    public static void addMatchPhrase(BoolQuery.Builder boolQueryBuild, String field, String value) {
        boolQueryBuild.must(query -> query.matchPhrase(matchPhraseQueryBuild -> matchPhraseQueryBuild.field(field).query(value).slop(1)));
    }

    /***
     * 多字段满足同一值
     * @param boolQueryBuild
     * @param fields
     * @param value
     */
    public static void addMultiMatch(BoolQuery.Builder boolQueryBuild, List<String> fields, String value) {
        boolQueryBuild.must(query -> query.multiMatch(multiMatchBuild -> multiMatchBuild.fields(fields).query(value).slop(10).fuzziness("2")));
    }


    public static void addMultiMatch(Query.Builder boolQueryBuild, List<String> fields, String value) {
        boolQueryBuild.multiMatch(multiMatchBuild -> multiMatchBuild.fields(fields).query(value).slop(1));
    }


    /**
     * 单一字段按范围查询
     *
     * @param boolQueryBuild
     * @param field
     * @param minValue
     * @param maxValue
     */

    public static void addRange(BoolQuery.Builder boolQueryBuild, String field, Serializable minValue, Serializable maxValue) {
        boolQueryBuild.must(mustQueryBuild -> mustQueryBuild.range(rangeQueryBuild -> {
            rangeQueryBuild.field(field);
            if (Objects.nonNull(minValue)) {
                rangeQueryBuild.from(minValue.toString());
            }
            if (Objects.nonNull(maxValue)) {
                rangeQueryBuild.to(maxValue.toString());
            }
            return rangeQueryBuild;
        }));
    }

    /**
     * 范围查询 数字类型
     *
     * @param boolQueryBuild
     * @param field
     * @param customBoundary
     */
    public static void addRange(BoolQuery.Builder boolQueryBuild, String field, Boundary customBoundary) {
        addRange(boolQueryBuild, field, customBoundary.getMinimum(), customBoundary.getMaximum());
    }


    /**
     * 范围查询时间类型
     *
     * @param boolQueryBuild
     * @param field
     * @param rangeTime
     */
    public static void addRange(BoolQuery.Builder boolQueryBuild, String field, BoundaryTime rangeTime) {
        addRange(boolQueryBuild, field, rangeTime.getStartTime(), rangeTime.getEndTime());
    }


}
